home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / SCSI Samples 1.0 / SCSI Async Sample 06⁄15 ƒ / Src / ContinueTesting.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-16  |  8.9 KB  |  320 lines  |  [TEXT/KAHL]

  1. /*                                    ContinueTesting.c                            */
  2. /*
  3.  * ContinueTesting.c
  4.  * Copyright © 93 Apple Computer Inc. All Rights Reserved.
  5.  *
  6.  * Run the dialog until the user has had enough.
  7.  */
  8. #include "SCSIAsyncSample.h"
  9. #include "SCSIDefinitions.h"
  10. pascal void
  11. PerformTestIOCompletion(
  12.         void                        *ioPtr
  13.     );
  14.  
  15. #define INFO        (*infoPtr)
  16.  
  17. void                                ComputeTestParameters(
  18.         register InfoPtr                infoPtr
  19.     );
  20. void                                PerformTest(
  21.         register InfoPtr                infoPtr
  22.     );
  23.     
  24.  
  25.  
  26. void
  27. StartTesting(void)
  28. {
  29.         InfoPtr                            infoPtr;
  30.  
  31.         for (infoPtr = (InfoPtr) infoPtrQueue.qHead;
  32.                 infoPtr != NULL;
  33.                 infoPtr = (InfoPtr) infoPtr->link) {
  34.             if (INFO.validDevice) {
  35.                 INFO.sampleSum = INFO.sampleSumSquare = 0.0;
  36.                 INFO.deviceActive = TRUE;
  37.                 Microseconds(&INFO.testStartTime);
  38.                 if (INFO.enableAsync) {
  39.                     /*
  40.                      * This loop is entered once when we start the actual test.
  41.                      * It is only called for asychronous threads.
  42.                      */
  43.                     ComputeTestParameters(infoPtr);
  44.                     PerformTest(infoPtr);
  45.                 }
  46.             }
  47.         }
  48. }
  49.  
  50. void
  51. ContinueTesting(void)
  52. {
  53.         InfoPtr                            infoPtr;
  54.         Boolean                            somethingIsBusy;
  55.         static Boolean                    stoppedYet = FALSE;
  56.         
  57.         somethingIsBusy = FALSE;
  58.         for (infoPtr = (InfoPtr) infoPtrQueue.qHead;
  59.                 infoPtr != NULL;
  60.                 infoPtr = (InfoPtr) infoPtr->link) {
  61.             if (INFO.deviceActive && INFO.testCompleted == FALSE) {
  62.                 somethingIsBusy = TRUE;
  63.                 if (INFO.enableAsync == FALSE) {
  64.                     /*
  65.                      * This loop is entered each time through the event loop to
  66.                      * read one request from a synchronous test thread. It is not
  67.                      * called for asychronous threads.
  68.                      */
  69.                     ComputeTestParameters(infoPtr);
  70.                     PerformTest(infoPtr);
  71.                 }
  72.             }
  73.         }
  74.         if (somethingIsBusy == FALSE) {
  75.             InitCursor();
  76.             if (stoppedYet == FALSE) {    
  77.                 stoppedYet = TRUE;
  78.                 DisplayTestResults();
  79.             }
  80.         }
  81. }
  82.  
  83. void VMStartMarker(void) { }
  84.  
  85. /*
  86.  * These may be called from an I/O completion routine
  87.  */
  88. void
  89. PerformTest(
  90.         register InfoPtr            infoPtr
  91.     )
  92. {
  93.         short                        commandLength;
  94.         OSErr                        status;
  95.         register short                i;
  96.         register SCSIExecIOPB        *pb;
  97.         register RequestMemoryPtr    requestMemoryPtr;
  98. #define PB (*pb)
  99.  
  100.         ClearMemory((Ptr) INFO.vmHoldInfo, sizeof INFO.vmHoldInfo);
  101.         CLEAR(INFO.command);
  102.         if (INFO.transferSizeBlocks <= 256
  103.          && INFO.blockCount <= 0x001FFFFFL) {
  104.             INFO.command.scsi6.opcode = kScsiCmdRead6;
  105.             INFO.command.scsi6.lbn3 = (INFO.blockNumber >> 16) & 0xFF;
  106.             INFO.command.scsi6.lbn2 = (INFO.blockNumber >>  8) & 0xFF;
  107.             INFO.command.scsi6.lbn1 = (INFO.blockNumber      ) & 0xFF;
  108.             INFO.command.scsi6.len  = INFO.transferSizeBlocks & 0xFF;
  109.             INFO.command.scsi6.lbn3 |= (INFO.deviceIdent.LUN << 5) & 0xE0;
  110.             commandLength = sizeof INFO.command.scsi6;
  111.         }
  112.         else {
  113.             INFO.command.scsi10.opcode = kScsiCmdRead6;
  114.             INFO.command.scsi10.lbn4 = (INFO.blockNumber    >> 24) & 0xFF;
  115.             INFO.command.scsi10.lbn3 = (INFO.blockNumber    >> 16) & 0xFF;
  116.             INFO.command.scsi10.lbn2 = (INFO.blockNumber    >>  8) & 0xFF;
  117.             INFO.command.scsi10.lbn1 = (INFO.blockNumber         ) & 0xFF;
  118.             INFO.command.scsi10.len2 = (INFO.transferSizeBlocks >> 8) & 0xFF;
  119.             INFO.command.scsi10.len1 = (INFO.transferSizeBlocks     ) & 0xFF;
  120.             INFO.command.scsi10.lun |= (INFO.deviceIdent.LUN << 5) & 0xE0;
  121.             commandLength = sizeof INFO.command.scsi10;
  122.         }
  123.         /*
  124.          * Plug the parameters into the SCSI command block.
  125.          */
  126.         pb = INFO.pb;
  127.         PB.scsiPBLength = INFO.pbSize;
  128.         PB.scsiFunctionCode = SCSIExecIO;
  129.         /*
  130.          * Use the private pointer in the SCSI command block to link the
  131.          * SCSI parameter block to the InfoRecord.
  132.          */
  133.         PB.scsiDriverStorage = (unsigned char *) infoPtr;
  134.         PB.scsiCompletion = (INFO.enableAsync) ? PerformTestIOCompletion : NULL;
  135.         PB.scsiTimeout = INFO.completionTimeout;
  136.         PB.scsiSelectTimeout = INFO.completionTimeout;
  137.         PB.scsiDevice = INFO.deviceIdent;
  138.         PB.scsiCDBLength = commandLength;
  139.         PB.scsiCDB.cdbPtr = (unsigned char *) &INFO.command;
  140.         PB.scsiFlags = (scsiCDBIsPointer | scsiSIMQNoFreeze);
  141.         PB.scsiFlags |= (INFO.enableDisconnect)
  142.                     ? scsiDoDisconnect
  143.                     : scsiDontDisconnect;
  144.         if (INFO.bufferPtr == NULL || INFO.bufferLength == 0)
  145.             PB.scsiFlags |= scsiDirectionNone;
  146.         else {
  147.             /*
  148.              * If the user specified the transfer quantum == 1, select "polled"
  149.              * transfers, otherwise, select "blind."
  150.              */
  151.             PB.scsiTransferType = (INFO.transferQuantum == 1)
  152.                         ? scsiTransferPolled
  153.                         : scsiTransferBlind;
  154.             PB.scsiDataPtr = (unsigned char *) INFO.bufferPtr;
  155.             PB.scsiDataLength = INFO.bufferLength;
  156.             PB.scsiDataType = scsiDataBuffer;
  157.             PB.scsiFlags |= scsiDirectionIn;
  158.             PB.scsiHandshake[0] = 512;
  159.             PB.scsiHandshake[1] = 0;
  160.  
  161.         }
  162.         INFO.senseData.errorCode = 0;
  163.         PB.scsiSensePtr = (unsigned char *) &INFO.senseData;
  164.         PB.scsiSenseLength = sizeof INFO.senseData;
  165.         if (gVirtualMemoryEnabled) {
  166.             /* Function */
  167.             /* Param block */
  168.             INFO.vmHoldInfo[kVMParam].ptr = INFO.pb;
  169.             INFO.vmHoldInfo[kVMParam].size = INFO.pbSize;
  170.             /* Data buffer */
  171.             INFO.vmHoldInfo[kVMBuffer].ptr = PB.scsiDataPtr;
  172.             INFO.vmHoldInfo[kVMBuffer].size = PB.scsiDataLength;
  173.             /* Info record (has command and sense buffer) */
  174.             INFO.vmHoldInfo[kVMSense].ptr = PB.scsiSensePtr;
  175.             INFO.vmHoldInfo[kVMSense].size = PB.scsiSenseLength;
  176.             for (i = 0; i < kVMSize; i++) {
  177.                 if (INFO.vmHoldInfo[i].ptr != NULL) {
  178.                     status = HoldMemory(
  179.                                 INFO.vmHoldInfo[i].ptr,
  180.                                 INFO.vmHoldInfo[i].size
  181.                             );
  182.                     if (status != noErr) {
  183.                         while (i < kVMSize)
  184.                             INFO.vmHoldInfo[i++].ptr = NULL;
  185.                         break;
  186.                     }
  187.                 }
  188.             }
  189.             if (status != noErr) {
  190.                 /*
  191.                  * Something failed. Unwind before exiting.
  192.                  */
  193.                 for (i = 0; i < kVMSize; i++) {
  194.                     if (INFO.vmHoldInfo[i].ptr != NULL) {
  195.                         (void) UnholdMemory(
  196.                                 INFO.vmHoldInfo[i].ptr,
  197.                                 INFO.vmHoldInfo[i].size
  198.                             );
  199.                     }
  200.                 }
  201.             }
  202.         }
  203.         /*
  204.          * What ho, here we go!
  205.          */
  206.         requestMemoryPtr = &INFO.requestMemory[INFO.transfersAttempted % kRequestMemory];
  207.         INFO.requestMemoryPtr = requestMemoryPtr;
  208.         requestMemoryPtr->blockNumber = INFO.blockNumber;
  209.         ++INFO.transfersAttempted;
  210.         Microseconds(&requestMemoryPtr->startTime);
  211.         status = SCSIAction((SCSI_PB *) pb);
  212.         if (PB.scsiResult == scsiRequestInProgress)
  213.             ++INFO.asynchRequests;
  214.         if (status != noErr) {
  215.             if (PB.scsiCompletion == NULL && PB.scsiResult == noErr)
  216.                 PB.scsiResult = status;
  217.             if (INFO.finalStatus == noErr)
  218.                 INFO.finalStatus = status;
  219.         }
  220.         /*
  221.          * If we're asychronous, just exit - the I/O completion routine will
  222.          * clean up the mess. If we're synchronous, we're done, so call the
  223.          * I/O completion routine ourself.
  224.          */
  225.         if (PB.scsiCompletion == NULL)
  226.             PerformTestIOCompletion(pb);            
  227. }
  228.  
  229. /*
  230.  * This is called by I/O completion.
  231.  */
  232. pascal void
  233. PerformTestIOCompletion(
  234.         void                        *ioPtr
  235.     )
  236. {
  237.         register SCSIExecIOPB        *pb;
  238.         register InfoPtr            infoPtr;
  239.         short                        i;
  240.         double                        sampleTime;
  241.         UnsignedWide                difference;
  242.         
  243.         pb = (SCSIExecIOPB *) ioPtr;
  244.         infoPtr = (InfoPtr) PB.scsiDriverStorage;
  245.         Microseconds(&INFO.requestMemoryPtr->endTime);
  246.         MicrosecondDelta(
  247.             &INFO.requestMemoryPtr->startTime,
  248.             &INFO.requestMemoryPtr->endTime,
  249.             &difference
  250.         );
  251.         sampleTime = MicrosecondToDouble(&difference) / 1000000.0;
  252.         INFO.sampleSum += sampleTime;
  253.         INFO.sampleSumSquare += (sampleTime * sampleTime);
  254.         /*
  255.          * Release virtual memory
  256.          */
  257.         for (i = 0; i < kVMSize; i++) {
  258.             if (INFO.vmHoldInfo[i].ptr != NULL) {
  259.                 (void) UnholdMemory(
  260.                         INFO.vmHoldInfo[i].ptr,
  261.                         INFO.vmHoldInfo[i].size
  262.                     );
  263.             }
  264.         }
  265.         ++INFO.transfersCompleted;
  266.         /*
  267.          * If an error occurred, set the global "stop" flag to prevent
  268.          * errors from cascading.
  269.          */
  270.         if (PB.scsiResult != noErr && INFO.finalStatus == noErr)
  271.             INFO.finalStatus = PB.scsiResult;
  272.         if (INFO.finalStatus != noErr)
  273.             INFO.testCompleted = TRUE;
  274.         else if (INFO.totalTransfers != 0
  275.               && INFO.transfersCompleted >= INFO.totalTransfers)
  276.             INFO.testCompleted = TRUE;
  277.         /*
  278.          * If we're running asychronously and are still alive, start the
  279.          * next transfer.
  280.          */
  281.         if (INFO.testCompleted) {
  282.             INFO.testEndTime = INFO.requestMemoryPtr->endTime;
  283.             INFO.deviceActive = FALSE;
  284.         }
  285.         else if (INFO.enableAsync) {
  286.             ComputeTestParameters(infoPtr);
  287.             PerformTest(infoPtr);
  288.         }
  289. }
  290.  
  291. void VMEndMarker(void) { }
  292.  
  293. void
  294. ComputeTestParameters(
  295.         register InfoPtr                infoPtr
  296.     )
  297. {
  298.         if (INFO.finalStatus != noErr
  299.          || (INFO.totalTransfers != 0
  300.           && INFO.transfersCompleted >= INFO.totalTransfers))
  301.             INFO.testCompleted = TRUE;
  302.         else if (INFO.enableRandomSeek) {
  303.             INFO.randomSeed = (INFO.randomSeed * 1103515245L) + 12345L;
  304.             INFO.nextBlockNumber = INFO.randomSeed % INFO.totalLogicalBlocks;
  305.             goto computeByteCount;
  306.         }
  307.         else {
  308.             if (INFO.nextBlockNumber >= INFO.totalLogicalBlocks)
  309.                 INFO.nextBlockNumber = 0;
  310. computeByteCount:
  311.             INFO.blockNumber = INFO.nextBlockNumber;
  312.             INFO.blockCount = INFO.transferSizeBlocks;
  313.             if (INFO.blockNumber + INFO.blockCount >= INFO.totalLogicalBlocks)
  314.                 INFO.blockCount = INFO.totalLogicalBlocks - INFO.blockNumber;
  315.             INFO.byteCount = INFO.transferSizeBlocks * INFO.logicalBlockLength;
  316.             INFO.nextBlockNumber = INFO.blockNumber + INFO.blockCount;
  317.         }
  318. }
  319.  
  320.